/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
package cgl.narada.jms;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.MessageFormatException;
import javax.jms.ObjectMessage;

/**
   This class implements the ObjectMessage specified in the JMS specification.

   @author Shrideep Pallickara
   $Revision$
   $Date$
*/

public class JmsObjectMessage extends JmsMessage implements ObjectMessage {
  private byte[] objectMessageBytes;
  private Serializable serializedObject;
  
  public JmsObjectMessage() {
    super();
    try {
      setJMSType("ObjectMessage");
    } catch (JMSException jmsEx) {
      System.out.println(jmsEx);
    }
  }
  
 
  public JmsObjectMessage(byte[] objectMsgBytes) {
    try {
      ByteArrayInputStream baInputStream = 
	new ByteArrayInputStream(objectMsgBytes);
      DataInputStream din = new DataInputStream(baInputStream);
      int headerAndPropertyLength = din.readInt();
      byte[] headerPropBytes = new byte[headerAndPropertyLength];
      din.readFully(headerPropBytes);
      super.unmarshallJmsMessage(headerPropBytes);
      
      objectMessageBytes = new byte[din.readInt()];
      din.readFully(objectMessageBytes);
    } catch (IOException ioe) {
      System.out.println("JmsObjectMessage:: Error in unmarshalling");
    }
    
    
    try {
      ByteArrayInputStream baInputStream = 
	new ByteArrayInputStream(objectMessageBytes);
      ObjectInputStream objectInputStream = 
	new ObjectInputStream(baInputStream);
      serializedObject = (Serializable) objectInputStream.readObject();
      objectInputStream.close();
    } catch (IOException exception) {
      System.out.println("\n" + "De-Serialization failed " +  
			 exception + "\n");
    } catch (ClassNotFoundException exception) {
      System.out.println("\n" + "De-Serialization failed " +  
			 exception + "\n");
    } /* end-try */ 
    
    /** If we have reached this stage, everything is alright. The 
	deserialization is now complete */
    try {
      setJMSType("ObjectMessage");
    } catch (JMSException jmsEx) {
      System.out.println(jmsEx);
    }
  }
  
  public byte[] getBytes() {
    ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
    DataOutputStream dout = new DataOutputStream(baOutputStream);
    byte[] marshalledBytes = null;
    try {
      byte[] headerPropBytes = super.getBytes();
      /* Write the length of the byte Stream comprising headers and properties
	 first.*/
      dout.writeInt(headerPropBytes.length);
      dout.write(headerPropBytes);
      
      /** Write down the length of the objectMessageBytes stream */
      dout.writeInt(objectMessageBytes.length);
      dout.write(objectMessageBytes);
      
      dout.flush();
      marshalledBytes = baOutputStream.toByteArray();
    } catch (IOException ioe) {
      System.out.println("JmsObjectMessage: Error marshalling ObjecttMessage");
    }/* end try-catch block */
    return marshalledBytes;
  }
  

  public void setObject(Serializable object) throws JMSException {
    /** This checks if the message's write properties would allow a 
	write operation to be performed. Throws a MessageNotWriteableException
	if there is a failure to do so */
    testWriteProperties();
    
    if (object == null) 
      throw new JMSException("The serializable object being added is NULL");
    try {
      ByteArrayOutputStream baOutputStream= new ByteArrayOutputStream();
      ObjectOutputStream objectOutputStream = 
	new ObjectOutputStream(baOutputStream);
      objectOutputStream.writeObject(object);

      objectOutputStream.flush();
      objectMessageBytes = baOutputStream.toByteArray();
      objectOutputStream.close();
      serializedObject= object;
    } catch (IOException exception) {
      throw new MessageFormatException("Error serializing object" + exception);
    }/* end-try */
   
  }
  
  public Serializable getObject() throws JMSException {
    if (objectMessageBytes == null)
      throw new JMSException("The object bytes for deserialization is NULL");
    return serializedObject;
  }
  
  public String toString() {
    String stringRep = super.toString() + "\n" + 
      " Object Message " + serializedObject;
    return stringRep;
  }

  public void clearBody() throws JMSException {
    super.clearBody();
    objectMessageBytes = null;
  }

  public static void main(String[] args) {
    JmsObjectMessage jmsObjMsg1,jmsObjMsg2,jmsObjMsg3,jmsObjMsg4, jmsObjMsg5;
    Hashtable table = new Hashtable();
    table.put("recorder.audio.filename", "shrideep");
    table.put("hey there buddy", "dude");
    try {
      jmsObjMsg1 = new JmsObjectMessage();
      jmsObjMsg1.setObject(table);
      jmsObjMsg2 = new JmsObjectMessage(jmsObjMsg1.getBytes());
      jmsObjMsg3 = new JmsObjectMessage(jmsObjMsg2.getBytes());
      jmsObjMsg4 = new JmsObjectMessage(jmsObjMsg3.getBytes());
      jmsObjMsg5 = new JmsObjectMessage(jmsObjMsg4.getBytes());
      System.out.println(jmsObjMsg5);
    } catch(JMSException jmsEx) {
      System.out.println(jmsEx);
    }/*end-try-catch */

    
  }/*end-main*/

}/*end-class*/


